#include "HttpServer.hpp"
#include "Err.hpp"
#include "Util.hpp"
#include <memory>
#include <vector>
#include <unordered_map>

const std::string SEP = "\r\n";
const std::string page_404 = "./wwwroot/err_404.html";
const std::string defaultHomePage = "index.html";
const std::string webRoot = "./wwwroot";

class HttpRequest
{
public:
    HttpRequest() :path_(webRoot)
    {}
    void Print()
    {
        logMessage(DEBUG, "method: %s, url: %s, version: %s",
                   method_.c_str(), url_.c_str(), httpVersion_.c_str());
        for(const auto & line : body_)
            logMessage(DEBUG, "-%s", line.c_str());
        logMessage(DEBUG, "textview: %s", textview_.c_str());
        logMessage(DEBUG, "path: %s", path_.c_str());
        logMessage(DEBUG, "suffix_: %s", suffix_.c_str());
    }
    ~HttpRequest()
    {}
public:
    std::string method_;
    std::string url_;
    std::string httpVersion_;
    std::vector<std::string> body_;
    std::string textview_;

    std::string path_;
    std::string suffix_;
};

HttpRequest Deserialize(std::string& message)
{
    HttpRequest req;
    std::string line = Util::ReadOneLine(message, SEP);
    Util::ParseRequestLine(line, &req.method_, &req.url_, &req.httpVersion_);

    while (!message.empty())
    {
        line = Util::ReadOneLine(message, SEP);
        if (line == "\r\n") break;
        req.body_.push_back(line);
    }
    req.textview_ = message;

    req.path_ += req.url_;
    if (req.path_[req.path_.size()-1] == '/')
        req.path_ += defaultHomePage;
    
    auto pos = req.path_.rfind(".");
    if (pos == std::string::npos) req.suffix_ = ".html";
    else req.suffix_ = req.path_.substr(pos);
    return req;
}

std::string GetContentType(const std::string& suffix)
{
    std::string content_type = "Content-Type: ";
    if (suffix == ".html" || suffix == ".htm") content_type += "text/html";
    else if (suffix == ".css") content_type += "text/css";
    else if (suffix == ".js") content_type += "application/x-javascript";
    else if (suffix == ".jpg") content_type += "image/jpeg";
    else if (suffix == ".png") content_type += "image/png";
    else
    {}
    return content_type + SEP;
}

class User_Data
{
public:
    std::string name;
    std::string passwd;
};

class Session
{
public:
    std::string name;
    std::string passwd;
    uint64_t loginTime;

    int status;
    int fd;
    int sessionid;
};

std::unordered_map<int, Session*> sessions;

// bool Login(const std::string& textview)
// {
//     auto pos1 = textview.find("=");
//     auto pos2 = textview.find("&", pos1);
//     auto pos3 = textview.rfind("=");
//     std::string name = textview.substr(pos1, pos2-pos1);
//     std::string passwd = textview.substr(pos3);

//     if (check(name, passwd))
//     {
//         Session* session = new Session(name, passwd);
//         int random = rand();
//     }
// }



std::string HandlerHttp(std::string& message)
{
    std::cout << "-----------------------------------" << std::endl;
    std::cout << message << std::endl;
    std::cout << "-----------------------------------" << std::endl;

    HttpRequest req = Deserialize(message);
    req.Print();

    std::string body;
    std::string response;
    if (true == Util::Readfile(req.path_, &body))
    {
        response = "HTTP/1.0 200 OK" + SEP;
        response += "Content-Length: " + std::to_string(body.size()) + SEP;
        response += GetContentType(req.suffix_);
        response += SEP;
        response += body;
    }
    else
    {
        response = "HTTP/1.0 404 Not Found" + SEP;
        Util::Readfile(page_404, &body);
        response += "Content-Length: " + std::to_string(body.size()) + SEP;
        response += GetContentType(".html");
        response += SEP;
        response += body;
    }

    // 重定向测试
    // std::string response;
    // response = "HTTP/1.0 302 Found" + SEP;
    // response += "Location: https://www.qq.com/" + SEP;
    // response += SEP;

    // cookie && session 实验
    // std::string response;
    // response = "HTTP/1.0 200 OK" +SEP;
    // response += "Set-Cookie: sessionid=1234abcd" + SEP;
    // response += SEP;

    return response;
}

int main(int argc, char* argv[])
{
    if (argc != 2) 
    {
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    std::unique_ptr<HttpServer> tsvr(new HttpServer(HandlerHttp, port));
    tsvr->InitServer();
    tsvr->Start();
    return 0;
}